package main

import (
	"context"
	"errors"
	"fmt"
	"log"
	"login-server/config"
	"login-server/routes"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/gin-gonic/gin"
)

// main 是应用程序的入口点
func main() {
	// 配置日志格式
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
	log.Println("开始启动登录服务器...")

	// 加载配置
	err := config.InitGlobalConfig("config.yaml")
	if err != nil {
		log.Fatalf("加载配置错误: %v", err)
	}
	// 加载数据库
	config.InitDB()

	// 根据配置设置gin模式
	serverConfig := config.GlobalConfig.Server
	gin.SetMode(serverConfig.Env)

	// 初始化路由器
	router := gin.New()

	// 添加日志记录和恢复中间件
	router.Use(gin.Logger())
	router.Use(gin.Recovery())

	// 初始化路由
	routes.SetupRoutes(router)

	// 设置HTTP服务器
	server := &http.Server{
		Addr:    fmt.Sprintf(":%d", serverConfig.Port),
		Handler: router,
		// 添加超时设置
		ReadTimeout:  15 * time.Second,
		WriteTimeout: 15 * time.Second,
		IdleTimeout:  60 * time.Second,
	}

	// 服务器运行上下文
	serverCtx, serverStopCtx := context.WithCancel(context.Background())

	// 监听系统信号以进行进程生命周期管理
	sig := make(chan os.Signal, 1)
	signal.Notify(sig, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
	go func() {
		// 一直阻塞等待
		<-sig

		// 带有30秒宽限期的关闭信号
		shutdownCtx, cancel := context.WithTimeout(serverCtx, 30*time.Second)
		defer cancel()

		// 如果超时，强制退出
		go func() {
			<-shutdownCtx.Done()
			if errors.Is(shutdownCtx.Err(), context.DeadlineExceeded) {
				log.Fatal("优雅关闭超时..强制退出。")
			}
		}()

		// 触发优雅关闭，阻塞等待30秒退出
		log.Println("正在关闭服务器...")
		if err := server.Shutdown(shutdownCtx); err != nil {
			log.Fatal(err)
		}
		serverStopCtx()
	}()

	// 启动服务器
	log.Printf("登录服务器在端口 %d 上启动，环境：%s\n", serverConfig.Port, serverConfig.Env)
	if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
		log.Fatal(err)
	}

	// 等待服务器上下文停止
	<-serverCtx.Done()
	log.Println("服务器已停止")
}
